package com.huyun.web.FutureTest;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * @program:
 * @description: 查询所有商店某个商品的价格并返回，并且查询商店某个商品的价格的API为同步 一个Shop类，提供一个名为getPrice的同步方法
 * 查询商品的价格为同步方法，并通过sleep方法模拟其他操作。这个场景模拟了当需要调用第三方API，但第三方提供的是同步API，
 * 在无法修改第三方API时如何设计代码调用提高应用的性能和吞吐量，这时候可以使用CompletableFuture类
 * @create: 2021-12-30 10:34
 */
public class CompltableFulterTest {
    //店铺为一个列表：
    private static List<Shop> shopList = Arrays.asList(
            new Shop("BestPrice"),
            new Shop("LetsSaveBig"),
            new Shop("MyFavoriteShop"),
            new Shop("BuyItAll")
    );
    //同步方法：
    private  static List<String> findPriceSync(String product){

        return shopList.stream().map(shop ->
                String.format("%s price is %.2f",shop.getName(), shop.getPrice(product)))
                .collect(Collectors.toList());
    }

    //异步方法：
    private static List<String> findPriceAsync(String product) {
        List<CompletableFuture<String>> completableFutureList = shopList.stream()
                //转异步执行
                .map(shop -> CompletableFuture.supplyAsync(
                        () -> String.format("%s price is %.2f",
                                shop.getName(), shop.getPrice(product))))  //格式转换
                .collect(Collectors.toList());

        return completableFutureList.stream()
                .map(CompletableFuture::join)  //获取结果不会抛出异常
                .collect(Collectors.toList());
    }

    /**
         * 在JDK1.8以前，通过调用线程池的submit方法可以让任务以异步的方式运行，该方法会返回一个Future对象，通过调用get方法获取异步执行的结果
     */
    private static List<String> findPriceFutureAsync(String product) {
        ExecutorService es = Executors.newCachedThreadPool();
        List<Future<String>> futureList = shopList.stream().map(shop -> es.submit(() -> String.format("%s price is %.2f",
                shop.getName(), shop.getPrice(product)))).collect(Collectors.toList());

        return futureList.stream()
                .map(f -> {
                    String result = null;
                    try {
                        result = f.get();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (ExecutionException e) {
                        e.printStackTrace();
                    }

                    return result;
                }).collect(Collectors.toList());
    }



    public static void main(String[] args) {
        long starttime = System.currentTimeMillis();
       List<String> price = findPriceFutureAsync("BestPrice");
//        List<String> price = findPriceAsync("BestPrice");
        for(String s:price){
            System.out.println("价格=="+s);
        }
        long endtime = System.currentTimeMillis();
        System.out.println(endtime-starttime);



    }

}
